/*
 * Copyright Debezium Authors.
 *
 * Licensed under the Apache Software License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
 */

package io.debezium.connector.opengauss.connection;

import java.nio.ByteBuffer;
import java.sql.SQLException;
import java.util.function.Function;

import io.debezium.connector.opengauss.TypeRegistry;
import org.postgresql.replication.fluent.logical.ChainedLogicalStreamBuilder;

/**
 * A class that is able to deserialize/decode binary representation of a batch of replication messages generated by
 * logical decoding plugin. Clients provide a callback code for processing.
 *
 * @author Jiri Pechanec
 *
 */
public interface MessageDecoder {

    /**
     * Process a message upon arrival from logical decoder
     *
     * @param buffer - binary representation of replication message
     * @param processor - message processing on arrival
     * @param typeRegistry - registry with known types
     */
    void processMessage(ByteBuffer buffer, ReplicationStream.ReplicationMessageProcessor processor, TypeRegistry typeRegistry) throws SQLException, InterruptedException;

    /**
     * Allows MessageDecoder to configure options with which the replication stream is started.
     * The messages CAN contain type metadata.
     * See PostgreSQL command START_REPLICATION SLOT for more details.
     *
     * @param builder
     * @return the builder instance
     */
    ChainedLogicalStreamBuilder optionsWithMetadata(ChainedLogicalStreamBuilder builder, Function<Integer, Boolean> hasMinimumServerVersion);

    /**
     * Allows MessageDecoder to configure options with which the replication stream is started.
     * The messages MUST NOT contain type metadata.
     * See PostgreSQL command START_REPLICATION SLOT for more details.
     *
     * @param builder
     * @return the builder instance
     */
    ChainedLogicalStreamBuilder optionsWithoutMetadata(ChainedLogicalStreamBuilder builder, Function<Integer, Boolean> hasMinimumServerVersion);

    /**
     * Signals to this decoder whether messages contain type metadata or not.
     */
    // TODO DBZ-508 Remove once we only support LD plug-ins always sending the metadata
    default void setContainsMetadata(boolean flag) {
    }

    /**
     * A callback into the decoder allowing it to decide whether the supplied message should be processed
     * by the decoder or whether it can be skipped.
     *
     * @param buffer the replication stream buffer
     * @param lastReceivedLsn the last LSN reported by the replication stream
     * @param startLsn the starting LSN reported by the streaming producer
     * @param walPosition wal position from which the streaming should resume
     * @return {@code true} if the incoming message should be skipped, {@code false} otherwise
     */
    boolean shouldMessageBeSkipped(ByteBuffer buffer, Lsn lastReceivedLsn, Lsn startLsn, WalPositionLocator walPosition);

    /**
     * Closes this decoder, freeing and/or closing all resources it may potentially hold.
     */
    void close();
}
